#ifndef HTTPCONNECT_H
#define HTTPCONNECT_H

#include"epoll_add_del.h"
#include<arpa/inet.h>
#include<iostream>
#include<errno.h>
#include<strings.h>
#include<sys/types.h>
// #include<regex>
#include<string.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<sys/mman.h>
#include<stdarg.h>
#include<stdio.h>
// #include"lst_timer.h"
using namespace std;

#define FILENAME_LEN 200 //允许请求文件的长度
#define READ_BUFFER_SIZE  2048  //读缓冲区的大小
#define WRITE_BUFFER_SIZE  1024 //写缓冲区的大小


class util_timer;

class http_connect{
public:
    static int m_epollfd; //所有的socket上的事件都被注册到同一个epoll事件中 
    static int m_user_count; //统计用户的数量
    int m_sockfd; //该HTTP连接的SOCKET

    /*
    
    //每个连接都有一个定时器，为了后面该连接传入数据后重置定时器，所以需要该
    http_time
    */
    util_timer* http_time;
  
     // HTTP请求方法，这里只支持GET
    enum METHOD {GET = 0, POST, HEAD, PUT, DELETE, TRACE, OPTIONS, CONNECT};
    
    /*
        解析客户端请求时，主状态机的状态
        CHECK_STATE_REQUESTLINE:当前正在分析请求行
        CHECK_STATE_HEADER:当前正在分析头部字段
        CHECK_STATE_CONTENT:当前正在解析请求体
    */
    enum CHECK_STATE { CHECK_STATE_REQUESTLINE = 0, CHECK_STATE_HEADER, CHECK_STATE_CONTENT };
    
    /*
        服务器处理HTTP请求的可能结果，报文解析的结果
        NO_REQUEST          :   请求不完整，需要继续读取客户数据
        GET_REQUEST         :   表示获得了一个完成的客户请求
        BAD_REQUEST         :   表示客户请求语法错误
        NO_RESOURCE         :   表示服务器没有资源
        FORBIDDEN_REQUEST   :   表示客户对资源没有足够的访问权限
        FILE_REQUEST        :   文件请求,获取文件成功
        INTERNAL_ERROR      :   表示服务器内部错误
        CLOSED_CONNECTION   :   表示客户端已经关闭连接了
    */
    enum HTTP_CODE { NO_REQUEST, GET_REQUEST, BAD_REQUEST, NO_RESOURCE, FORBIDDEN_REQUEST, FILE_REQUEST, INTERNAL_ERROR, CLOSED_CONNECTION };
    
    // 从状态机的三种可能状态，即行的读取状态，分别表示
    // 1.读取到一个完整的行 2.行出错 3.行数据尚且不完整
    enum LINE_STATUS { LINE_OK = 0, LINE_BAD, LINE_OPEN };


    http_connect();
    ~http_connect();

    void init(int connfd,const sockaddr_in& client_address,util_timer* timer); //初始化新接收的连接

    void close_connection(); //关闭连接

    void process(); //处理客户端的请求 

    bool read(); //非阻塞读
    
    bool write(); //非阻塞写

    HTTP_CODE process_read(); //解析HTTP请求
    HTTP_CODE parse_request_line(char* text); //解析请求首行
    HTTP_CODE parse_request_headers(char* text); //解析请求头
    HTTP_CODE parse_request_content(char* text); //解析请求内容
    LINE_STATUS parse_line(); // 解析某一个具体的行

    bool process_write(HTTP_CODE read_ret); //根据请求状态生成响应内容
    bool add_status_line(int status,const char* title); //添加响应状态行
    bool add_headers(int content_length);
    bool add_content_length(int contrnt_length);
    bool add_content_type();
    bool add_linger();
    bool add_blank_line();
    bool add_content(const char* content);
    bool add_response(const char* format,...); 
    

    

private: 
    

   
    sockaddr_in m_address; //通信的socket地址 
    char m_read_buf[READ_BUFFER_SIZE]; //读缓冲区
    int m_read_idx; //标识读缓冲区中以及读入的客户端数据的最后一个字节的下一个位置

     CHECK_STATE m_check_state;  //主状态机当前所处的状态
    int m_checked_index;  //当前正在分析的字符在读缓冲器的位置
    int m_start_line; //当前正在解析的行的起始位置

    /*
        下面是请求行所携带的内容
    */
    char* m_url; //请求目标文件的文件名
    char* m_vesion; //协议版本号，只支持http1.1
    METHOD m_function; //请求的方法
    /**/

    /*
    下面是请求头携带的信息
    */

   char* m_host; //请求主机信息
   bool m_linger; //是否保持连接

   /**/

   /*
   下面是请求体需要的一部分信息
   */
    int m_content_length;
    /**/


    /*
    处理完整请求的相关信息
    */

   char m_real_file[200]; //存放请求文件的路径
   struct stat m_file_stat; //存放请求文件的相关信息
   char* m_file_address;  //请求的目标文件被mmap到内存中的起始位置
   void unmap();

    /*
    生成相应信息相关信息
    */

   char m_write_buf[WRITE_BUFFER_SIZE];  //写缓冲区
   int m_write_index;
   struct iovec m_iv[2];
   int m_iv_count;

   




   

    void init(); //初始化一些其它的数据

    //获取处理行于m_read_buf中的起始位置
    inline char* get_line(){
        return m_read_buf+m_start_line;
    }


    //http请求数据获取完整，实际的处理
    HTTP_CODE do_request();


    




};

#endif